/*
 * Copyright (c) 2021 柯华栋
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <ctype.h>
#include "ipc_client.h"


// -----------------------------------------------------------------------------------------

#define get_new_capcity_by_size(x) (((x) + 16) * 3 / 2)

typedef struct {
	gchar* 				module_name;
	gchar*				server_name;
	GDBusConnection*	connection;
	int 				size;
	int 				capacity;
	gchar** 			ids;
} module_t;


typedef struct {
	int 		size;
	int 		capacity;
	module_t** 	items;
} module_map_t;


typedef struct {
	gchar*		id;
	int 		size;
	int 		capacity;
	gint64* 	data;
} observers_t;

typedef struct {
	int 			size;
	int 			capacity;
	observers_t** 	items;
} observers_map_t;

// 通过id寻找模块(模块又包含所有被监听的id)
static module_map_t 	s_module_map;

// 通过id寻找监听器列表
static observers_map_t 	s_observers_map;

// 用于添加调试信息给client_send, client_pos
static gchar* s_client_name = NULL;

// 通过模块名寻找要连接的服务
static ipc_map_t* s_module_server_map;

// 服务名和连接的映射
static id_pointer_map_t* s_server_connection_map;

// ----------------------------------------------------------------------------------------

static module_t* module_new(const gchar* module_name)
{
	module_t* module = (module_t*) malloc(sizeof(module_t));
	module->module_name = g_strdup(module_name);

	ipc_lock();	
	const gchar* server_name = ipc_map_get_string(s_module_server_map, module_name);	
	module->server_name = (server_name == NULL) ? module->module_name : g_strdup(server_name);
	ipc_unlock();
	
	module->connection = NULL;
	module->size = 0;
	module->capacity = get_new_capcity_by_size(0);
	module->ids = (gchar**) malloc(sizeof(gchar*) * module->capacity);
	return module;
}

static int module_get_pos(module_t* module, const gchar* id)
{
	int first = 0;
    int last = module->size;

    while (last > first) {
        int next = (last + first) >> 1;
        int cmp = strcmp(id, module->ids[next]);
        if (!cmp)
            return -next - 1;
        if (cmp < 0) {
            last = next;
            continue;
        }
        first = next + 1;
    }
    return first;
}

static void module_insert_pos(module_t* module, int pos, const gchar* id)
{
	assert(pos >= 0);

	// 空间满，重新分配
	if (module->size == module->capacity) {
		module->capacity = get_new_capcity_by_size(module->size);
		module->ids = (gchar**) realloc(module->ids, sizeof(gchar*) * module->capacity);
	}

	module->size++;
	// 不添加在末端, 留出位置
	if (module->size > pos) {
		memmove(module->ids + pos + 1, module->ids + pos, sizeof(gchar*) * (module->size - pos - 1));
	}
	module->ids[pos] = str_check_dup(id);
}

static void module_remove_pos(module_t* module, int pos)
{
	assert(pos < 0);

	pos = -pos - 1;
	str_check_free(module->ids[pos]);
	module->ids[pos] = NULL;
	module->size--;
	if (pos < module->size) {
		memmove(module->ids + pos, module->ids + pos + 1, sizeof(gchar*) * (module->size - pos));
	}
}

// -----------------------------------------------------------------------------------------------

static int module_map_get_pos(const gchar* module_name)
{
	int first = 0;
    int last = s_module_map.size;

    while (last > first) {
        int next = (last + first) >> 1;
        int cmp = strcmp(module_name, s_module_map.items[next]->module_name);
        if (!cmp)
            return -next - 1;
        if (cmp < 0) {
            last = next;
            continue;
        }
        first = next + 1;
    }
    return first;
}


static void module_map_insert_pos(int pos, module_t* module)
{
	assert(pos >= 0);

	// 空间满，重新分配
	if (s_module_map.size == s_module_map.capacity) {
		s_module_map.capacity = get_new_capcity_by_size(s_module_map.size);
		s_module_map.items = (module_t**) realloc(s_module_map.items, sizeof(module_t*) * s_module_map.capacity);
	}

	s_module_map.size++;
	// 不添加在末端, 留出位置
	if (s_module_map.size > pos) {
		memmove(s_module_map.items + pos + 1, s_module_map.items + pos, sizeof(module_t*) * (s_module_map.size - pos - 1));
	}
	s_module_map.items[pos] = module;
}

static void module_map_clear_connection(GDBusConnection* connection)
{
	ipc_lock();
	for (int i = 0; i < s_module_map.size; i++) {
		if (s_module_map.items[i]->connection == connection) {
			s_module_map.items[i]->connection = NULL;
		}
	}
	
	int size = id_pointer_map_size(s_server_connection_map);
	for (int i = 0; i < size; i++) {		
		if ((GDBusConnection*) id_pointer_map_get_pointer_by_pos(s_server_connection_map, i) == connection) {
			id_pointer_map_set_pointer_by_pos(s_server_connection_map, i, NULL);
			break;
		}
	}
	
	ipc_unlock();
}


// ----------------------------------------------------------------------------------------

static observers_t* observers_new(const gchar* id)
{
	observers_t* observers = (observers_t*)malloc(sizeof(observers_t));
	observers->id = str_check_dup(id);
	observers->size = 0;
	observers->capacity = get_new_capcity_by_size(0);
	observers->data = (gint64*) malloc(sizeof(gint64) * observers->capacity);
	return observers;
}

static void observers_free(observers_t* observers)
{
	str_check_free(observers->id);
	free(observers->data);
	free(observers);
}

static int observers_get_pos(observers_t* observers, gint64 observer)
{
	int first = 0;
    int last = observers->size;

    while (last > first) {
        int next = (last + first) >> 1;
        gint64 cmp = observer - observers->data[next];
        if (!cmp)
            return -next - 1;
        if (cmp < 0) {
            last = next;
            continue;
        }
        first = next + 1;
    }
    return first;
}

static void observers_insert_pos(observers_t* observers, int pos, gint64 observer)
{
	assert(pos >= 0);

	// 空间满，重新分配
	if (observers->size == observers->capacity) {
		observers->capacity = get_new_capcity_by_size(observers->size);
		observers->data = (gint64*) realloc(observers->data, sizeof(gint64) * observers->capacity);
	}

	observers->size++;
	// 不添加在末端, 留出位置
	if (observers->size > pos) {
		memmove(observers->data + pos + 1, observers->data + pos, sizeof(gint64) * (observers->size - pos - 1));
	}
	observers->data[pos] = observer;
}

static void observers_remove_pos(observers_t* observers, int pos)
{
	assert(pos < 0);

	pos = -pos - 1;
	observers->size--;
	if (pos < observers->size) {
		memmove(observers->data + pos, observers->data + pos + 1, sizeof(gint64) * (observers->size - pos));
	}
}


// ----------------------------------------------------------------------------------------

static int observers_map_get_pos(const gchar* id)
{
	int first = 0;
    int last = s_observers_map.size;

    while (last > first) {
        int next = (last + first) >> 1;
        int cmp = strcmp(id, s_observers_map.items[next]->id);
        if (!cmp)
            return -next - 1;
        if (cmp < 0) {
            last = next;
            continue;
        }
        first = next + 1;
    }
    return first;
}

static void observers_map_insert_pos(int pos, observers_t* observers)
{
	assert(pos >= 0);

	// 空间满，重新分配
	if (s_observers_map.size == s_observers_map.capacity) {
		s_observers_map.capacity = get_new_capcity_by_size(s_observers_map.size);
		s_observers_map.items = (observers_t**) realloc(s_observers_map.items, sizeof(observers_t*) * s_observers_map.capacity);
	}

	s_observers_map.size++;
	// 不添加在末端, 留出位置
	if (s_observers_map.size > pos) {
		memmove(s_observers_map.items + pos + 1, s_observers_map.items + pos, sizeof(observers_t*) * (s_observers_map.size - pos - 1));
	}
	s_observers_map.items[pos] = observers;
}

static void observers_map_remove_pos(int pos)
{
	assert(pos < 0);
	pos = -pos - 1;
	observers_free(s_observers_map.items[pos]);
	s_observers_map.items[pos] = NULL;
	s_observers_map.size--;
	if (pos < s_observers_map.size) {
		memmove(s_observers_map.items + pos, s_observers_map.items + pos + 1, sizeof(observers_t*) * (s_observers_map.size - pos));
	}
}


// -----------------------------------------------------------------------------------------

/** 再进行ipc调用前先设定模块的服务名(如果不设置，服务名就是模块名), 用于共享连接，减少连接数 */
void client_set_module_server_name(const gchar* module_name, const gchar* server_name)
{
	assert(module_name != NULL && module_name[0] != 0 && strchr(module_name, '.') == NULL);
	assert(server_name != NULL && server_name[0] != 0);	
	ipc_map_set_string(s_module_server_map, module_name, server_name);
}

/** 通过配置文件设置模块的服务名 */
void client_set_module_server_name_by_config_file(void)
{
	char line[1024];	
	
	FILE* file = fopen("module_server_name.properties", "r");	
	if (!file) {
		g_print("can not open module_server_name.properties\n");
		return;
	}
	while (fgets(line, 1024, file)) {
		// 删除注释
		char* p = strchr(line, '#');
		if (p) {
			*p = 0;
		}
		
		// 寻找=
		p = strchr(line, '=');
		if (!p) {
			continue;
		}
		
		// key, value
		const gchar* key_begin = line;
		const gchar* key_end = p-1;
		const gchar* value_begin = p+1;
		const gchar* value_end = &line[strlen(line)-1];
		
		// 去除空格
		while (key_begin <= key_end && isspace(*key_begin)) {
			key_begin++;
		}
		while (key_begin <= key_end && isspace(*key_end)) {
			key_end--;
		}
		
		while (value_begin <= value_end && isspace(*value_begin)) {
			value_begin++;
		}
		while (value_begin <= value_end && isspace(*value_end)) {
			value_end--;
		}
		
		if (key_begin <= key_end && value_begin <= value_end) {
			gchar* module_name = g_strndup(key_begin, key_end-key_begin+1);
			gchar* server_name = g_strndup(value_begin, value_end-value_begin+1);
			if (!strchr(module_name, '.')) {
				client_set_module_server_name(module_name, server_name);
				printf("module_name = %s, server_name = %s\n", module_name, server_name);
			}
			g_free(module_name);
			g_free(server_name);
		}
	}
	fclose(file);
}

/** 获取在监听中的id */
ipc_string_array_t* client_get_observing_ids()
{
	ipc_lock();
	
	ipc_string_array_t* array = ipc_string_array_new(s_observers_map.size);
	for (int i = 0; i < s_observers_map.size; i++) {
		ipc_string_array_set(array, i, s_observers_map.items[i]->id);
	}
	
	ipc_unlock();
	
	return array;
}

struct _ipc_observer_array_t {
	int 			ref_cnt;
	int 			size;
	ipc_observer_t* data[0];
};

/** 获取指定id的监听器 */
ipc_observer_array_t* client_get_ipc_observer_array(const gchar* id)
{
	if (id == NULL || id[0] == 0) {
		return NULL;
	}
	
	ipc_lock();

	ipc_observer_array_t* ret = NULL;
	int observers_pos = observers_map_get_pos(id);
	if (observers_pos >= 0) {
		goto finish;
	}
	
	observers_t* observers = s_observers_map.items[-observers_pos-1];
	ret = (ipc_observer_array_t*) malloc(
		sizeof(ipc_observer_array_t) + sizeof(ipc_observer_t*) * observers->size);
	ret->ref_cnt = 1;
	ret->size = observers->size;
	for (int i = 0; i < ret->size; i++) {
		ret->data[i] = (ipc_observer_t*)observers->data[i];
	}
	
finish:
	ipc_unlock();
	return ret;
}

/** 添加和删除引用 */
int ipc_observer_array_ref(ipc_observer_array_t* array)
{
	if (array != NULL)
	{
		ipc_lock();
		assert(array->ref_cnt > 0);
		array->ref_cnt++;
		int cnt = array->ref_cnt;
		ipc_unlock();
		return cnt;
	}
	return 0;
}

int ipc_observer_array_unref(ipc_observer_array_t* array)
{
	if (array != NULL)
	{
		ipc_lock();
		assert(array->ref_cnt > 0);
		array->ref_cnt--;
		if (array->ref_cnt == 0)
		{
			/* value在array内从块中 */
			free(array);
			ipc_unlock();
			return 0;
		}
		int cnt = array->ref_cnt;
		ipc_unlock();
		return cnt;
	}
	return 0;
}

int ipc_observer_array_size(ipc_observer_array_t* array)
{
	assert(array);
	return array->size;	
}

ipc_observer_t* ipc_observer_array_get(ipc_observer_array_t* array, int pos)
{
	assert(array);
	assert(pos >= 0 && pos < array->size);
	return array->data[pos];
}

// -----------------------------------------------------------------------------------------

/* 函数回调 */
static void on_callback(GDBusConnection* connection,
	const gchar* sender, const gchar* object_path, const gchar*	interface_name,
	const gchar* method_name,
	GVariant* parameters, GDBusMethodInvocation* invocation, gpointer user_data)
{
	ipc_map_t* map = ipc_map_from_variant(parameters);
	if (map == NULL)
		return;
	const gchar* id = 	ipc_map_get_string(map, IPC_MAP_KEY_ID);
	int64_t observer = 	ipc_map_get_s64(map, IPC_MAP_KEY_OBSERVER);
	if (id == NULL || id[0] == 0)
		return;

	// 回调给observer
	ipc_lock();

	int observers_pos = observers_map_get_pos(id);
	if (observers_pos < 0) {
		observers_t* observers = s_observers_map.items[-observers_pos-1];
		if (observer == 0) {
			// 每一个
			for (int i = 0; i < observers->size; i++) {
				ipc_observer_t* observer = (ipc_observer_t*)observers->data[i];
				observer->on_update(observer->ud, map);
			}
		} else {
			// 指定的一个
			int observer_pos = observers_get_pos(observers, observer);
			if (observer_pos < 0) {
				ipc_observer_t* observer = (ipc_observer_t*)observers->data[-observer_pos-1];
				observer->on_update(observer->ud, map);
			}
		}
	}

	ipc_unlock();

	ipc_map_unref(map);
}

static const GDBusInterfaceVTable interface_vtable =
{
	on_callback,
	NULL,
	NULL,
};


/* 连接关闭 */
static void connection_closed(
	GDBusConnection*	connection,
	gboolean 			remote_peer_vanished,
	GError*				Error,
	gpointer			user_data)
{
	g_print("connection_closed\n");
	module_map_clear_connection(connection);
	// 取消引用
	g_object_unref(connection);
}


static const gchar k_node_info_xml[] =
"<node>"
"  <interface name='com.car.ipc.Channel'>"
"    <method name='post'>"
"      <arg type='ay' name='data' direction='in'/>"
"    </method>"
"  </interface>"
"</node>";

static GDBusConnection* connection_new(const gchar* module_name)
{
	// 地址
	gchar* address = g_strdup_printf("unix:abstract=%s", module_name);

	// 错误信息
	GError* error = NULL;

	GDBusConnection* connection = g_dbus_connection_new_for_address_sync(
		address,
		G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
		NULL, NULL, &error);

	// 连接失败
	if (connection == NULL) {
		// 打印连接失败原因
		g_printerr("Error connecting to D-Bus address %s: %s\n", address, error->message);
		g_error_free(error);
	}

	// 节点信息
	static GDBusNodeInfo* node_info = NULL;
	if (node_info == NULL)
		node_info = g_dbus_node_info_new_for_xml(k_node_info_xml, NULL);

	// 监听断开连接
	g_signal_connect(connection, "closed", G_CALLBACK(connection_closed), NULL);

	// 注册接口虚表
	guint id UNUSED_MARK = g_dbus_connection_register_object(
		connection,
		"/com/car/ipc/Channel",
		node_info->interfaces[0],
		&interface_vtable,
		NULL, 	/* user_data */
		NULL, 	/* user_data_free_func */
		NULL	/* GError */
	);

	return connection;
}


static void connection_post(GDBusConnection* connection, ipc_map_t* map)
{
	// 附加调试信息
	ipc_map_set_string(map, IPC_MAP_KEY_CLIENT, s_client_name);
	g_dbus_connection_call(connection,
		NULL, "/com/car/ipc/Channel", "com.car.ipc.Channel", "post",
		ipc_map_to_variant(map), NULL,
		G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}


static ipc_map_t* connection_send(GDBusConnection* connection, ipc_map_t* map)
{
	// 附加调试信息
	ipc_map_set_string(map, IPC_MAP_KEY_CLIENT, s_client_name);
	// 发送
	GVariant* parameters = g_dbus_connection_call_sync(connection,
		NULL, "/com/car/ipc/Channel", "com.car.ipc.Channel", "send",
		ipc_map_to_variant(map), G_VARIANT_TYPE("(ay)"),
		G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);

	// 返回
	ipc_map_t* ret = ipc_map_from_variant(parameters);
	g_variant_unref(parameters);
	return ret;

}


static void connection_add_id(GDBusConnection* connection, const gchar* id, gint64 observer)
{
	g_dbus_connection_call(connection,
		NULL, "/com/car/ipc/Channel", "com.car.ipc.Channel", "add_id",
		g_variant_new("(@(sx))", g_variant_new("(sx)", id, observer)), NULL,
		G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}

static void connection_remove_id(GDBusConnection* connection, const gchar* id)
{
	g_dbus_connection_call(connection,
		NULL, "/com/car/ipc/Channel", "com.car.ipc.Channel", "remove_id",
		g_variant_new("(s)", id), NULL,
		G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}


// --------------------------------------------------------------------------------------------

static inline GDBusConnection* get_connection(module_t* module, int try_cnt)
{
	GDBusConnection* connection = module->connection;
	if (connection == NULL) {
		connection = id_pointer_map_get(s_server_connection_map, module->server_name);
	}
	
	int index = 0;
	while (connection == NULL) {
		if (index != 0)
			usleep(200*1000);
		index++;
		module->connection = connection = connection_new(module->server_name);		
		if (connection != NULL) {
			id_pointer_map_set(s_server_connection_map, module->server_name, connection);
		}
		if (index == try_cnt)
			break;
	}
	return connection;
}

static gboolean check_and_reconnect(gpointer data)
{
	(void)data;
	ipc_lock();

	for (int i = 0; i < s_module_map.size; i++) {
		module_t* module = s_module_map.items[i];
		// 断开了连接，但是还有id被监听，需要重新连接，并添加id到服务
		if (module->connection == NULL && module->size != 0) {
			module->connection = get_connection(module, 1);
			if (module->connection != NULL) {
				for (int j = 0; j < module->size; j++) {
					connection_add_id(module->connection, module->ids[j], 0);
				}
			}
		}
	}

	ipc_unlock();
	return TRUE;
}


void client_init(const gchar* client_name)
{
	assert(client_name && client_name[0] != 0);
	s_client_name = str_check_dup(client_name);
	
	s_module_server_map = ipc_map_new();
	s_server_connection_map = id_pointer_map_new();
	
	g_timeout_add(1000, check_and_reconnect, NULL);
	
	// 使用配置文件进行配置
	client_set_module_server_name_by_config_file();
}


static gchar* get_module_name(const gchar* id, gchar* buffer, int size)
{
	if (id == NULL) {
		return NULL;
	}

	const gchar* name_after = strchr(id, '.');
	int len = name_after-id;
	if (name_after == NULL || len == 0) {
		return NULL;
	}

	if (len < size) {
		memcpy(buffer, id, len);
		buffer[len] = 0;
		return buffer;
	}
	return g_strndup(id, name_after-id);
}

void client_post(ipc_map_t* map)
{
	if (map == NULL) {
		return;
	}

	gchar buffer[64];	// 避免频繁的创建和释放
	const gchar* id = ipc_map_get_string(map, IPC_MAP_KEY_ID);
	gchar* module_name = get_module_name(id, buffer, 64);
	if (module_name == NULL) {
		// 减少map引用
		ipc_map_unref(map);
		return;
	}

	ipc_lock();

	module_t* module = NULL;
	int module_pos = module_map_get_pos(module_name);
	if (module_pos >= 0) {
		module = module_new(module_name);
		module_map_insert_pos(module_pos, module);
	} else {
		module = s_module_map.items[-module_pos-1];
	}

	GDBusConnection* connection = get_connection(module, 3);
	if (connection != NULL) {
		connection_post(connection, map);
	}

	ipc_unlock();

	if (module_name != buffer)
		g_free(module_name);
	// 减少map引用
	ipc_map_unref(map);
}

ipc_map_t* client_send(ipc_map_t* map)
{
	if (map == NULL) {
		return NULL;
	}

	gchar buffer[64];	// 避免频繁的创建和释放
	const gchar* id = ipc_map_get_string(map, IPC_MAP_KEY_ID);
	gchar* module_name = get_module_name(id, buffer, 64);
	if (module_name == NULL) {
		// 减少map引用
		ipc_map_unref(map);
		return NULL;
	}

	ipc_lock();

	module_t* module = NULL;
	int module_pos = module_map_get_pos(module_name);
	if (module_pos >= 0) {
		module = module_new(module_name);
		module_map_insert_pos(module_pos, module);
	} else {
		module = s_module_map.items[-module_pos-1];
	}

	GDBusConnection* connection = get_connection(module, 3);
	ipc_map_t* ret_map = NULL;
	if (connection != NULL) {
		ret_map = connection_send(connection, map);
	}

	ipc_unlock();

	if (module_name != buffer)
		g_free(module_name);
	// 减少map引用
	ipc_map_unref(map);

	return ret_map;
}

void client_add_observer(const gchar* id, ipc_observer_t* observer)
{
	gchar buffer[64];	// 避免频繁的创建和释放
	gchar* module_name = get_module_name(id, buffer, 64);
	if (module_name == NULL || observer == NULL) {
		return;
	}

	ipc_lock();

	observers_t* observers = NULL;
	module_t* module = NULL;

	int observers_pos = observers_map_get_pos(id);
	// 此id还没监听器
	if (observers_pos >= 0) {
		observers = observers_new(id);
		observers_map_insert_pos(observers_pos, observers);

		int module_pos = module_map_get_pos(module_name);
		// 此模块还没进行过ipc
		if (module_pos >= 0) {
			module = module_new(module_name);
			module_map_insert_pos(module_pos, module);
		} else {
			module = s_module_map.items[-module_pos-1];
		}

		// id没被监听肯定还没添加，反之一定被添加了
		int id_pos = module_get_pos(module, id);
		assert(id_pos >= 0);
		module_insert_pos(module, id_pos, id);
	} else {
		observers = s_observers_map.items[-observers_pos-1];
	}

	int observer_pos = observers_get_pos(observers, (gint64)observer);
	if (observer_pos >= 0) {
		observers_insert_pos(observers, observer_pos, (gint64)observer);
	}

	if (module == NULL) {
		int module_pos = module_map_get_pos(module_name);
		assert(module_name < 0);
		module = s_module_map.items[-module_pos-1];
	}

	// 如果是NULL, 这里不用进行ipc, 会留待定时器去处理
	GDBusConnection* connection = module->connection;
	if (connection != NULL) {
		connection_add_id(connection, id, (gint64)observer);
	}

	ipc_unlock();

	if (module_name != buffer) {
		g_free(module_name);
	}
}

void client_remove_observer(const gchar* id, ipc_observer_t* observer)
{
	gchar buffer[64];	// 避免频繁的创建和释放
	gchar* module_name = get_module_name(id, buffer, 64);
	if (module_name == NULL || observer == NULL) {
		return;
	}

	ipc_lock();

	int observers_pos = observers_map_get_pos(id);
	if (observers_pos >= 0) {
		goto finish;
	}

	observers_t* observers = s_observers_map.items[-observers_pos-1];
	int observer_pos = observers_get_pos(observers, (gint64)observer);
	if (observer_pos >= 0) {
		goto finish;
	}

	// 移除observer
	observers_remove_pos(observers, observer_pos);

	if (observers->size == 0) {
		// observers没有任何observer了, 移除observers
		observers_map_remove_pos(observers_pos);

		int module_pos = module_map_get_pos(module_name);
		assert(module_pos < 0);

		module_t* module = s_module_map.items[-module_pos-1];
		int id_pos = module_get_pos(module, id);
		assert(id_pos < 0);

		// 移除id
		module_remove_pos(module, id_pos);

		// 移除服务中的id (如果是NULL, 这里不用进行ipc, 因为代表连接断开了, 服务端会自动清除)
		GDBusConnection* connection = module->connection;
		if (connection != NULL) {
			connection_remove_id(connection, id);
		}
	}

finish:
	ipc_unlock();

	if (module_name != buffer) {
		g_free(module_name);
	}
}


// post衍生函数(只附加一个_value参数) ---------------------------------------------------
void client_post_u8(const gchar* id, uint8_t value)
{
	client_post(ipc_map_new_id_u8(id, value));
}

void client_post_s16(const gchar* id, int16_t value)
{
	client_post(ipc_map_new_id_s16(id, value));
}

void client_post_s32(const gchar* id, int32_t value)
{
	client_post(ipc_map_new_id_s32(id, value));
}

void client_post_s64(const gchar* id, int64_t value)
{
	client_post(ipc_map_new_id_s64(id, value));
}

void client_post_float(const gchar* id, float value)
{
	client_post(ipc_map_new_id_float(id, value));
}

void ipc_post_double(const gchar* id, double value)
{
	client_post(ipc_map_new_id_double(id, value));
}

void client_post_string(const gchar* id, const gchar* value)
{
	client_post(ipc_map_new_id_string(id, value));
}


void client_post_u8_array(const gchar* id, ipc_u8_array_t* array)
{
	client_post(ipc_map_new_id_u8_array(id, array));
}

void client_post_s16_array(const gchar* id, ipc_s16_array_t* array)
{
	client_post(ipc_map_new_id_s16_array(id, array));
}

void client_post_s32_array(const gchar* id, ipc_s32_array_t* array)
{
	client_post(ipc_map_new_id_s32_array(id, array));
}

void client_post_s64_array(const gchar* id, ipc_s64_array_t* array)
{
	client_post(ipc_map_new_id_s64_array(id, array));
}

void client_post_float_array(const gchar* id, ipc_float_array_t* array)
{
	client_post(ipc_map_new_id_float_array(id, array));
}

void client_post_double_array(const gchar* id, ipc_double_array_t* array)
{
	client_post(ipc_map_new_id_double_array(id, array));
}

void client_post_string_array(const gchar* id, ipc_string_array_t* array)
{
	client_post(ipc_map_new_id_string_array(id, array));
}

// --------------------------------------------------------------------------------------
// send衍生函数(只附加一个“_value”参数)
// 如果返回值只有一个参数可以使用ipc_map_get_xxx(map, KEY_VALUE)来获取
ipc_map_t* client_send_u8(const gchar* id, uint8_t value)
{
	return client_send(ipc_map_new_id_u8(id, value));
}

ipc_map_t* client_send_s16(const gchar* id, int16_t value)
{
	return client_send(ipc_map_new_id_s16(id, value));
}

ipc_map_t* client_send_s32(const gchar* id, int32_t value)
{
	return client_send(ipc_map_new_id_s32(id, value));
}

ipc_map_t* client_send_s64(const gchar* id, int64_t value)
{
	return client_send(ipc_map_new_id_s64(id, value));
}

ipc_map_t* client_send_float(const gchar* id, float value)
{
	return client_send(ipc_map_new_id_float(id, value));
}

ipc_map_t* client_send_double(const gchar* id, double value)
{
	return client_send(ipc_map_new_id_double(id, value));
}

ipc_map_t* client_send_string(const gchar* id, const gchar* value)
{
	return client_send(ipc_map_new_id_string(id, value));
}


ipc_map_t* client_send_u8_array(const gchar* id, ipc_u8_array_t* array)
{
	return client_send(ipc_map_new_id_u8_array(id, array));
}

ipc_map_t* client_send_s16_array(const gchar* id, ipc_s16_array_t* array)
{
	return client_send(ipc_map_new_id_s16_array(id, array));
}

ipc_map_t* client_send_s32_array(const gchar* id, ipc_s32_array_t* array)
{
	return client_send(ipc_map_new_id_s32_array(id, array));
}

ipc_map_t* client_send_s64_array(const gchar* id, ipc_s64_array_t* array)
{
	return client_send(ipc_map_new_id_s64_array(id, array));
}

ipc_map_t* client_send_float_array(const gchar* id, ipc_float_array_t* array)
{
	return client_send(ipc_map_new_id_float_array(id, array));
}

ipc_map_t* client_send_double_array(const gchar* id, ipc_double_array_t* array)
{
	return client_send(ipc_map_new_id_double_array(id, array));
}

ipc_map_t* client_send_string_array(const gchar* id, ipc_string_array_t* array)
{
	return client_send(ipc_map_new_id_string_array(id, array));
}

